//! GICv3 register definitions
//!
//! Based on ARM GICv3 Architecture Specification and Linux kernel headers

// Distributor registers
pub const GICD_CTLR: usize = 0x0000;
pub const GICD_TYPER: usize = 0x0004;
pub const GICD_IIDR: usize = 0x0008;
pub const GICD_STATUSR: usize = 0x0010;
pub const GICD_SETSPI_NSR: usize = 0x0040;
pub const GICD_CLRSPI_NSR: usize = 0x0048;
pub const GICD_IGROUPR: usize = 0x0080;
pub const GICD_ISENABLER: usize = 0x0100;
pub const GICD_ICENABLER: usize = 0x0180;
pub const GICD_ISPENDR: usize = 0x0200;
pub const GICD_ICPENDR: usize = 0x0280;
pub const GICD_ISACTIVER: usize = 0x0300;
pub const GICD_ICACTIVER: usize = 0x0380;
pub const GICD_IPRIORITYR: usize = 0x0400;
pub const GICD_ITARGETSR: usize = 0x0800;
pub const GICD_ICFGR: usize = 0x0C00;
pub const GICD_IGRPMODR: usize = 0x0D00;
pub const GICD_NSACR: usize = 0x0E00;
pub const GICD_IROUTER: usize = 0x6000;
pub const GICD_PIDR2: usize = 0xFFE8;

// Extended SPI registers
pub const GICD_IGROUPRnE: usize = 0x1000;
pub const GICD_ISENABLERnE: usize = 0x1200;
pub const GICD_ICENABLERnE: usize = 0x1400;
pub const GICD_ISPENDRnE: usize = 0x1600;
pub const GICD_ICPENDRnE: usize = 0x1800;
pub const GICD_ISACTIVERnE: usize = 0x1A00;
pub const GICD_ICACTIVERnE: usize = 0x1C00;
pub const GICD_IPRIORITYRnE: usize = 0x2000;
pub const GICD_ICFGRnE: usize = 0x3000;
pub const GICD_IROUTERnE: usize = 0x8000;

// GICD_CTLR bit definitions
pub const GICD_CTLR_RWP: u32 = 1 << 31;
pub const GICD_CTLR_DS: u32 = 1 << 6;
pub const GICD_CTLR_ARE_NS: u32 = 1 << 4;
pub const GICD_CTLR_ENABLE_G1A: u32 = 1 << 1;
pub const GICD_CTLR_ENABLE_G1: u32 = 1 << 0;

// GICD_TYPER bit definitions
pub const GICD_TYPER_RSS: u32 = 1 << 26;
pub const GICD_TYPER_LPIS: u32 = 1 << 17;
pub const GICD_TYPER_MBIS: u32 = 1 << 16;
pub const GICD_TYPER_ESPI: u32 = 1 << 8;

// GICD_IROUTER bit definitions
pub const GICD_IROUTER_SPI_MODE_ONE: u64 = 0 << 31;
pub const GICD_IROUTER_SPI_MODE_ANY: u64 = 1 << 31;

// GIC version detection
pub const GIC_PIDR2_ARCH_MASK: u32 = 0xf0;
pub const GIC_PIDR2_ARCH_GICv3: u32 = 0x30;
pub const GIC_PIDR2_ARCH_GICv4: u32 = 0x40;

// Redistributor registers (RD_base)
pub const GICR_CTLR: usize = 0x0000;
pub const GICR_IIDR: usize = 0x0004;
pub const GICR_TYPER: usize = 0x0008;
pub const GICR_STATUSR: usize = 0x0010;
pub const GICR_WAKER: usize = 0x0014;
pub const GICR_SETLPIR: usize = 0x0040;
pub const GICR_CLRLPIR: usize = 0x0048;
pub const GICR_PROPBASER: usize = 0x0070;
pub const GICR_PENDBASER: usize = 0x0078;
pub const GICR_INVLPIR: usize = 0x00A0;
pub const GICR_INVALLR: usize = 0x00B0;
pub const GICR_SYNCR: usize = 0x00C0;
pub const GICR_PIDR2: usize = 0xFFE8;

// GICR_CTLR bit definitions
pub const GICR_CTLR_ENABLE_LPIS: u32 = 1 << 0;
pub const GICR_CTLR_RWP: u32 = 1 << 3;

// GICR_WAKER bit definitions
pub const GICR_WAKER_ProcessorSleep: u32 = 1 << 1;
pub const GICR_WAKER_ChildrenAsleep: u32 = 1 << 2;

// GICR_TYPER bit definitions
pub const GICR_TYPER_PLPIS: u32 = 1 << 0;
pub const GICR_TYPER_VLPIS: u32 = 1 << 1;
pub const GICR_TYPER_DIRTY: u32 = 1 << 2;
pub const GICR_TYPER_DirectLPIS: u32 = 1 << 3;
pub const GICR_TYPER_LAST: u32 = 1 << 4;

// Redistributor registers (SGI_base, offset 64KB from RD_base)
pub const GICR_IGROUPR0: usize = 0x0080;
pub const GICR_ISENABLER0: usize = 0x0100;
pub const GICR_ICENABLER0: usize = 0x0180;
pub const GICR_ISPENDR0: usize = 0x0200;
pub const GICR_ICPENDR0: usize = 0x0280;
pub const GICR_ISACTIVER0: usize = 0x0300;
pub const GICR_ICACTIVER0: usize = 0x0380;
pub const GICR_IPRIORITYR0: usize = 0x0400;
pub const GICR_ICFGR0: usize = 0x0C00;
pub const GICR_IGRPMODR0: usize = 0x0D00;
pub const GICR_NSACR: usize = 0x0E00;

// CPU Interface system registers (ICC_*)
// EOImode for ICC_CTLR_EL1
pub const ICC_CTLR_EL1_EOImode_SHIFT: u32 = 1;
pub const ICC_CTLR_EL1_EOImode_drop_dir: u32 = 0 << ICC_CTLR_EL1_EOImode_SHIFT;
pub const ICC_CTLR_EL1_EOImode_drop: u32 = 1 << ICC_CTLR_EL1_EOImode_SHIFT;
pub const ICC_CTLR_EL1_EOImode_MASK: u32 = 1 << ICC_CTLR_EL1_EOImode_SHIFT;

// Priority mask
pub const ICC_CTLR_EL1_PRI_BITS_SHIFT: u32 = 8;
pub const ICC_CTLR_EL1_PRI_BITS_MASK: u32 = 0x7 << ICC_CTLR_EL1_PRI_BITS_SHIFT;

// Interrupt ID ranges
pub const INTID_SGI_MIN: u32 = 0;
pub const INTID_SGI_MAX: u32 = 15;
pub const INTID_PPI_MIN: u32 = 16;
pub const INTID_PPI_MAX: u32 = 31;
pub const INTID_SPI_MIN: u32 = 32;
pub const INTID_SPI_MAX: u32 = 1019;
pub const INTID_SPECIAL_MIN: u32 = 1020;
pub const INTID_SPURIOUS: u32 = 1023;

// Extended PPI/SPI base
pub const EPPI_BASE_INTID: u32 = 1056;
pub const ESPI_BASE_INTID: u32 = 4096;

// GIC sizes
pub const GIC_V3_DIST_SIZE: usize = 0x10000;
pub const GIC_V3_REDIST_SIZE: usize = 0x20000;
